package cn.z2huo.usercenter.management.app.controller;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *
 * @author z2huo
 */
@Slf4j
@RestController
public class DownloadFileController {

    /**
     * <p>一次性下载多个文件，通过 ResponseEntity
     * <p>使用小文件试一下先
     */
    public ResponseEntity<byte[]> downloadMultiFile() {
        log.info("downloadLargeFile start");
        try {
            ClassPathResource classPathResource = new ClassPathResource("csv/problem/NO_0003/test_data_10000.csv");
            ClassPathResource classPathResource2 = new ClassPathResource("csv/problem/NO_0003/test_data_10000_2.csv");

            String fileName = "多个文件-1.csv";

            ContentDisposition contentDisposition = ContentDisposition.attachment()
                    .filename(fileName, StandardCharsets.UTF_8)
                    .build();

            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.CONTENT_ENCODING, "UTF-8");
            headers.setContentDisposition(contentDisposition);

            ResponseEntity<byte[]> body = ResponseEntity.ok()
                    .headers(headers)
                    .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                    .contentLength(classPathResource.contentLength())
                    .body(classPathResource.getContentAsByteArray());
            log.info("downloadLargeFile end");
            return body;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * <p>大文件下载，使用 ResponseEntity
     * @return  返回字节数组
     */
    @GetMapping("/downloadLargeFile")
    public ResponseEntity<byte[]> downloadLargeFile() {
        log.info("downloadLargeFile start");
        try {
//            ClassPathResource classPathResource = new ClassPathResource("csv/problem/NO_0003/test_data_10000.csv");
            ClassPathResource classPathResource = new ClassPathResource("csv/problem/NO_0003/test_data_5000000.csv");

            String fileName = "大csv文件.csv";

            ContentDisposition contentDisposition = ContentDisposition.attachment()
                    .filename(fileName, StandardCharsets.UTF_8)
                    .build();

            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.CONTENT_ENCODING, "UTF-8");
            headers.setContentDisposition(contentDisposition);

            ResponseEntity<byte[]> body = ResponseEntity.ok()
                    .headers(headers)
                    .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                    .contentLength(classPathResource.contentLength())
                    .body(classPathResource.getContentAsByteArray());
            log.info("downloadLargeFile end");
            return body;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * <p>大文件下载，使用输出流
     */
    @GetMapping("/downloadLargeFileOutputStream")
    public void downloadLargeFileOutputStream(HttpServletResponse response) {
        log.info("downloadLargeFileOutputStream start");

        ClassPathResource resource = new ClassPathResource("csv/problem/NO_0003/test_data_5000000.csv");

//        String fileName = "大csv文件.csv";
        String fileName = URLEncoder.encode("大csv文件.csv", StandardCharsets.UTF_8).replace("+", "%20");

        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setContentLength((int) resource.contentLength());
            response.setCharacterEncoding("UTF-8");
            response.setHeader(HttpHeaders.CONTENT_ENCODING, "UTF-8");
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName);
            // 与 Content-Length 冲突：如果使用了 Transfer-Encoding: chunked，则不能设置 Content-Length 头部。
//            response.setHeader(HttpHeaders.TRANSFER_ENCODING, "chunked");
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }

        try (InputStream inputStream = resource.getInputStream()) {
            ServletOutputStream outputStream = response.getOutputStream();
            byte[] bufferByteArray = new byte[1024 * 1024];
            int bytesReadCount;
            int loopCount = 1;
            while ((bytesReadCount = inputStream.read(bufferByteArray)) != -1) {
                TimeUnit.MILLISECONDS.sleep(100);
                log.info("loop count {}, read byte count is {}", loopCount++, bytesReadCount);
                outputStream.write(bufferByteArray, 0, bytesReadCount);
                outputStream.flush();
            }
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("downloadLargeFileOutputStream end");
    }

    /**
     * <p>将多个文件打包并下载压缩包
     *
     */
    @PostMapping("/")
    public void downloadZipFile() {

    }

    /**
     * 大文件分段下载
     * @param rangeHeader
     * @param response
     * @return
     * @throws IOException
     */
    @Deprecated
    public ResponseEntity<byte[]> downloadLargeFileRange(@RequestHeader(value = "Range", required = false) String rangeHeader,
                                       HttpServletResponse response) throws IOException {

        log.info("downloadLargeFileRange start");

        ClassPathResource resource = new ClassPathResource("csv/problem/NO_0003/test_data_5000000.csv");

//        String fileName = "大csv文件.csv";
        String fileName = URLEncoder.encode("大csv文件.csv", StandardCharsets.UTF_8).replace("+", "%20");

        long fileLength = resource.contentLength();
        List<HttpRange> ranges = HttpRange.parseRanges(rangeHeader);

        if (ranges.isEmpty()) {

            log.info("no range");

            ContentDisposition contentDisposition = ContentDisposition.attachment()
                    .filename(fileName, StandardCharsets.UTF_8)
                    .build();

            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.CONTENT_ENCODING, "UTF-8");
            headers.setContentDisposition(contentDisposition);

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                    .contentLength(resource.contentLength())
                    .body(resource.getContentAsByteArray());
        } else {
            HttpRange range = ranges.getFirst();
            long start = range.getRangeStart(fileLength);
            long end = range.getRangeEnd(fileLength);
            long rangeLength = end - start + 1;

        }

        log.info("downloadLargeFileRange end");

        return null;
    }

}
